#include "../mqserver/mq_host.hpp"
#include <gtest/gtest.h>

class HostTest : public testing::Test
{
public:
    virtual void SetUp() override
    {
        std::unordered_map<std::string,std::string> empty_map = std::unordered_map<std::string, std::string>();
        _vhp = std::make_shared<mq::VirtualHost>("host1","./data/host1/message/","./data/host1/host1.db");

        _vhp->declareExchange("exchange1",mq::ExchangeType::DIRECT,true,false,empty_map);
        _vhp->declareExchange("exchange2",mq::ExchangeType::DIRECT,true,false,empty_map);
        _vhp->declareExchange("exchange3",mq::ExchangeType::DIRECT,true,false,empty_map);

        _vhp->declareQueue("queue1",true,false,false,empty_map);
        _vhp->declareQueue("queue2",true,false,false,empty_map);
        _vhp->declareQueue("queue3",true,false,false,empty_map);

        _vhp->bind("exchange1","queue1","news.music.pop");
        _vhp->bind("exchange1","queue2","news.music.pop");
        _vhp->bind("exchange1","queue3","news.music.pop");

        _vhp->bind("exchange2","queue1","news.music.pop");
        _vhp->bind("exchange2","queue2","news.music.pop");
        _vhp->bind("exchange2","queue3","news.music.pop");

        _vhp->bind("exchange3","queue1","news.music.pop");
        _vhp->bind("exchange3","queue2","news.music.pop");
        _vhp->bind("exchange3","queue3","news.music.pop");

        _vhp->basicPublish("queue1",nullptr,"Hello World-1");
        _vhp->basicPublish("queue1",nullptr,"Hello World-2");
        _vhp->basicPublish("queue1",nullptr,"Hello World-3");

        _vhp->basicPublish("queue2",nullptr,"Hello World-1");
        _vhp->basicPublish("queue2",nullptr,"Hello World-2");
        _vhp->basicPublish("queue2",nullptr,"Hello World-3");

        _vhp->basicPublish("queue3",nullptr,"Hello World-1");
        _vhp->basicPublish("queue3",nullptr,"Hello World-2");
        _vhp->basicPublish("queue3",nullptr,"Hello World-3");
    }
    virtual void TearDown() override
    {
        _vhp->clear();
    }

public:
    mq::VirtualHost::ptr _vhp;
};

TEST_F(HostTest,init_test)
{
    ASSERT_EQ(_vhp->existsExchange("exchange1"),true);
    ASSERT_EQ(_vhp->existsExchange("exchange2"),true);
    ASSERT_EQ(_vhp->existsExchange("exchange3"),true);

    ASSERT_EQ(_vhp->existsQueue("queue1"),true);
    ASSERT_EQ(_vhp->existsQueue("queue2"),true);
    ASSERT_EQ(_vhp->existsQueue("queue3"),true);

    ASSERT_EQ(_vhp->existsBinding("exchange1","queue1"),true);
    ASSERT_EQ(_vhp->existsBinding("exchange1","queue2"),true);
    ASSERT_EQ(_vhp->existsBinding("exchange1","queue3"),true);

    ASSERT_EQ(_vhp->existsBinding("exchange2","queue1"),true);
    ASSERT_EQ(_vhp->existsBinding("exchange2","queue2"),true);
    ASSERT_EQ(_vhp->existsBinding("exchange2","queue3"),true);

    ASSERT_EQ(_vhp->existsBinding("exchange3","queue1"),true);
    ASSERT_EQ(_vhp->existsBinding("exchange3","queue2"),true);
    ASSERT_EQ(_vhp->existsBinding("exchange3","queue3"),true);

    mq::MessagePtr mp1 = _vhp->basicConsume("queue1");
    ASSERT_EQ(mp1->payload().body(),"Hello World-1");

    mq::MessagePtr mp2 = _vhp->basicConsume("queue1");
    ASSERT_EQ(mp2->payload().body(),"Hello World-2");

    mq::MessagePtr mp3 = _vhp->basicConsume("queue1");
    ASSERT_EQ(mp3->payload().body(),"Hello World-3");

    mq::MessagePtr mp4 = _vhp->basicConsume("queue1");
    ASSERT_EQ(mp4.get(), nullptr);
}

TEST_F(HostTest, remove_exchange) {
    _vhp->deleteExchange("exchange1");
    ASSERT_EQ(_vhp->existsExchange("exchange1"),false);
    ASSERT_EQ(_vhp->existsBinding("exchange1", "queue1"), false);
    ASSERT_EQ(_vhp->existsBinding("exchange1", "queue2"), false);
    ASSERT_EQ(_vhp->existsBinding("exchange1", "queue3"), false);
}

// TEST_F(HostTest, remove_queue) {
//     _vhp->deleteQueue("queue1");
//     ASSERT_EQ(_vhp->existsQueue("queue1"),false);
//     ASSERT_EQ(_vhp->existsBinding("exchange1", "queue1"), false);
//     ASSERT_EQ(_vhp->existsBinding("exchange2", "queue1"), false);
//     ASSERT_EQ(_vhp->existsBinding("exchange3", "queue1"), false);
    
//     mq::MessagePtr mp1 = _vhp->basicConsume("queue1");
//     ASSERT_EQ(mp1.get(), nullptr);
// }

TEST_F(HostTest, ack_message) {
    mq::MessagePtr mp1 = _vhp->basicConsume("queue1");
    ASSERT_EQ(mp1->payload().body(), std::string("Hello World-1"));
    _vhp->basicAck(std::string("queue1"), mp1->payload().properties().id());

    mq::MessagePtr mp2 = _vhp->basicConsume("queue1");
    ASSERT_EQ(mp2->payload().body(), std::string("Hello World-2"));
    _vhp->basicAck(std::string("queue1"), mp2->payload().properties().id());

    mq::MessagePtr mp3 = _vhp->basicConsume("queue1");
    ASSERT_EQ(mp3->payload().body(), std::string("Hello World-3"));
    _vhp->basicAck(std::string("queue1"), mp3->payload().properties().id());

}


int main(int argc, char *argv[])
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}